package com.greenline.push.service.core.task;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.greenline.push.core.enums.AppPacketSource;
import com.greenline.push.core.enums.Channels;
import com.greenline.push.core.enums.TaskStatus;
import com.greenline.push.core.enums.Tasks;
import com.greenline.push.core.pushcenter.MsgRetryFullManager;
import com.greenline.push.core.pushcenter.TaskSyncManager;
import com.greenline.push.dal.pushcenter.dataobject.MsgRetryDO;
import com.greenline.push.dal.pushcenter.dataobject.TaskSyncDO;
import com.greenline.push.service.core.ProcessQueueList;
import com.greenline.push.service.core.exception.TaskException;
import com.greenline.push.service.core.item.AppPacket;
import com.greenline.push.service.core.utils.Constants;

/**
 * 
 * @Type FetchRetryFullDataSchedule
 * @Desc load msg_retry_full表数据
 * @author shuai.zuo
 * @date 2014年10月16日
 * @Version V1.0
 */
public class FetchRetryFullDataSchedule extends TaskBase implements Runnable {
    @Autowired
    private TaskSyncManager taskSyncManager;
    private TaskSyncDO task = null;
    private Tasks taskType = null;
    private ProcessQueueList sendingQueue = null;
    private Long lastRecordId = null;
    private Channels channel = null;
    private final Integer MAX_MSG_COUNT = 1000;
    private static final String taskName = "{msg_retry_full数据获取}";
    @Autowired
    private MsgRetryFullManager msgRetryFullManager;
    private Logger log = Constants.LOG_SCHEDULE;
    // 定时任务没执行一次，生成唯一的识别号
    private String taskId = null;

    public void startTask(ProcessQueueList sendingQueue, Tasks task, Channels channel, long period, TimeUnit unit) throws TaskException {
        log.debug(String.format("%s--任务类型:<%s>开始启动----------", taskName, task));
        if (null == sendingQueue || null == task) {
            throw new TaskException("任务启动出错,queue不可为空,task不可为空");
        }
        // task init from here
        ScheduledExecutorService schedule = Executors.newScheduledThreadPool(1);

        this.sendingQueue = sendingQueue;
        this.taskType = task;
        this.channel = channel;
        schedule.scheduleAtFixedRate(this, 0, period, unit);
        log.debug(String.format("%s 任务类型:<%s>启动完成,运行周期:<%s>=========", taskName, task, period));
    }

    public FetchRetryFullDataSchedule(ProcessQueueList sendingQueue, Tasks taskType) {
        this.sendingQueue = sendingQueue;
        this.taskType = taskType;
    }

    public FetchRetryFullDataSchedule() {
    }

    @Override
    public void run() {
        excuteTask(new TaskCallBack() {
            @Override
            public TaskInfo initTaskInfo() {
                task = taskSyncManager.getTaskSyncByType(taskType.getType());
                // get uuid
                taskId = UUID.randomUUID().toString();

                log.debug(String.format("------定时任务开始执行----taskType:%s,tasks:%s,taskId:%s", taskType.getType(), taskType, taskId));

                TaskInfo taskInfo = new TaskInfo(taskName);
                // 无任务或者任务状态为running（status=1为running），task不能启动
                if (task == null) {
                    // here ,this return will broken the task forever.
                    log.debug(taskType + "-没有找到任务,停止执行。" + taskId);
                    return null;
                } else if (task.getStatus() == TaskStatus.RUNNING.getStatus()) {
                    log.debug(taskType + "-任务碰撞，停止执行。" + taskId);
                    taskInfo.setBizResult(TaskStatus.RUNNING.getName());
                    return taskInfo;
                } else {
                    task.setStatus(TaskStatus.RUNNING.getStatus());
                    taskSyncManager.update(task);

                    taskInfo.setBizResult(TaskStatus.END.getName());
                    return taskInfo;
                }
            }

            @Override
            public TaskInfo excute(TaskInfo taskInfo) {

                if (task == null) {
                    taskInfo.setSeccusss(false);
                    taskInfo.setBizResult("失败");
                    return taskInfo;
                }
                Long startId = task.getLastRecordId();
                lastRecordId = startId;
                // fetch max_msg_count records of type=1
                List<MsgRetryDO> msgRetryList = msgRetryFullManager.fetchMsgList(startId, MAX_MSG_COUNT, channel.getType());
                
                for (int i = 0; i < msgRetryList.size(); i++) {
                    MsgRetryDO tmp = msgRetryList.get(i);
                    AppPacket packet = JSON.parseObject(tmp.getPacketJson(), AppPacket.class);
                    packet.setDbRetryId(tmp.getId());
                    packet.setSource(AppPacketSource.FULL);
                    // insert queue
                    boolean insertResult = sendingQueue.offer(packet);

                    if (insertResult) {
                        lastRecordId = tmp.getId();
                    } else {
                        break;
                    }
                }
                // if fetch data &lt max_count means lastRecordId runs to the
                // last,then should return from zero
                if (msgRetryList.size() < MAX_MSG_COUNT) {
                    // if insert all the packets to queue,so we can set
                    // lastRecordId to zero;
                    if (msgRetryList.size() == 0 || lastRecordId == msgRetryList.get(msgRetryList.size() - 1).getId()) {
                        // set
                        lastRecordId = 0l;
                    }
                }
                // update status
                task.setLastRecordId(lastRecordId);
                task.setStatus(TaskStatus.END.getStatus());
                taskSyncManager.update(task);
                log.debug(String.format("%s--%s:--任务执行结束***任务id:%s", taskName, taskType, taskId));
                // update taskinfo
                taskInfo.setSeccusss(true);
                taskInfo.setCount((long) msgRetryList.size());
                taskInfo.setBizResult("成功");
                return taskInfo;
            }
        });
    }
}
